"""
温度映射核心算法模块
负责HSV颜色到温度的转换和标定插值计算
"""

import numpy as np


class TemperatureMapper:
    def __init__(self):
        self.calibration_points = []
        self.calibration_points_with_pos = []  # 存储包含位置信息的标定点
        self.temp_range = (20, 100)  # 默认温度范围
        
    def add_calibration_point(self, color_hsv, temperature, position=None):
        """添加标定点"""
        self.calibration_points.append((color_hsv, temperature))
        if position:
            # 存储位置、HSV颜色、温度信息
            self.calibration_points_with_pos.append({
                'position': position,
                'hsv': color_hsv,
                'temperature': temperature
            })
        
    def clear_calibration_points(self):
        """清空标定点"""
        self.calibration_points = []
        self.calibration_points_with_pos = []
        
    def remove_calibration_point(self, index: int) -> bool:
        """
        删除指定索引的标定点
        
        Args:
            index: 标定点索引
            
        Returns:
            是否删除成功
        """
        try:
            if 0 <= index < len(self.calibration_points_with_pos):
                # 删除带位置信息的标定点
                self.calibration_points_with_pos.pop(index)
                
                # 删除对应的基本标定点 (如果索引有效)
                if 0 <= index < len(self.calibration_points):
                    self.calibration_points.pop(index)
                
                return True
            return False
        except Exception:
            return False
        
    def get_calibration_info(self):
        """获取标定点的详细信息"""
        return self.calibration_points_with_pos
        
    def color_to_temperature(self, hsv_color):
        """将HSV颜色转换为温度"""
        if len(self.calibration_points) < 2:
            # 使用默认映射
            return self._default_mapping(hsv_color)
        else:
            # 使用标定点插值
            return self._interpolate_temperature(hsv_color)
    
    def _default_mapping(self, hsv_color):
        """默认颜色-温度映射"""
        h, s, v = hsv_color
        
        # 基于色调的温度映射
        if h < 30 or h > 330:  # 红色系 - 高温
            temp = 80 + (v / 255) * 20
        elif h < 60:  # 黄色系 - 中高温
            temp = 60 + (v / 255) * 20
        elif h < 120:  # 绿色系 - 中温
            temp = 40 + (v / 255) * 20
        elif h < 240:  # 蓝色系 - 低温
            temp = 20 + (v / 255) * 20
        else:  # 紫色系 - 最低温
            temp = 10 + (v / 255) * 30
            
        return max(self.temp_range[0], min(self.temp_range[1], temp))
    
    def _interpolate_temperature(self, hsv_color):
        """基于标定点插值计算温度"""
        if len(self.calibration_points) == 0:
            return self._default_mapping(hsv_color)
            
        # 确保输入数据类型正确
        hsv_color = np.array(hsv_color, dtype=np.float64)
            
        # 计算到各标定点的距离
        distances = []
        for cal_hsv, cal_temp in self.calibration_points:
            # 确保标定点数据类型正确
            cal_hsv = np.array(cal_hsv, dtype=np.float64)
            
            # 计算HSV空间中的欧几里得距离，添加安全检查
            h_diff = (hsv_color[0] - cal_hsv[0]) / 360.0
            s_diff = (hsv_color[1] - cal_hsv[1]) / 255.0
            v_diff = (hsv_color[2] - cal_hsv[2]) / 255.0
            
            dist = np.sqrt(h_diff ** 2 + s_diff ** 2 + v_diff ** 2)
            
            # 确保距离不为负数或无穷大
            if np.isnan(dist) or np.isinf(dist):
                dist = 1e6  # 设置一个很大的距离
            
            distances.append((dist, cal_temp))
        
        # 使用反距离权重插值
        if len(distances) == 1:
            return distances[0][1]
            
        total_weight = 0
        weighted_temp = 0
        
        for dist, temp in distances:
            if dist < 1e-6:  # 非常接近某个标定点
                return temp
            weight = 1.0 / (dist ** 2 + 1e-10)  # 添加小的常数避免除零
            total_weight += weight
            weighted_temp += weight * temp
        
        if total_weight > 0:
            return weighted_temp / total_weight
        else:
            return self._default_mapping(hsv_color)